/*
 * UDS_process.c
 *
 *  Created on: 2019��7��18��
 *      Author: nxf10035
 */
#include "UDS_process.h"
#include "watchdog_hal.h"
#include "timer_hal.h"
#include "bootloader_debug.h"

typedef struct
{
	uint32 msgId;
	uint32 msgLen;
	tpfTxMsgSuccCallback pfTxMsgCallback;
	uint8 isMsgValid;
	uint8 msgBuf[8];
}tMsgInfo;

typedef void (*tpfUDSService)(tMsgInfo *);

tMsgInfo g_RxMsgInfo;
tMsgInfo g_TxMsgInfo;

static void UDS_DiagnosticSession(void);

/*Do disable TX and RX non diagnostic message*/
static void UDS_DisableTXAndRXNonDiagnosticMsg(void);

/*Do disable record DTC*/
static void UDS_DisableRecordDTC(void);

uint8 IsBoot(void);
void SetBoot(uint8 val);


void UDS_Process_init(void)
{
    g_RxMsgInfo.isMsgValid = FALSE;
    g_RxMsgInfo.msgId = 0u;
    g_RxMsgInfo.msgLen = 0u;
    g_RxMsgInfo.pfTxMsgCallback = NULL_PTR;

    g_TxMsgInfo.isMsgValid = FALSE;
    g_TxMsgInfo.msgId = 0u;
    g_TxMsgInfo.msgLen = 0u;
    g_TxMsgInfo.pfTxMsgCallback = NULL_PTR;

    TIMER_HAL_Init();

    WATCHDOG_HAL_Init();

    BOOTLOADER_DEBUG_Init();

//Boot_CheckDownlaodAPPStatus();
    WATCHDOG_HAL_Fed();
}

void UDS_ProcessMain(void)
{
	static uint16 timerCnt = 0u;

	if(TRUE == TIMER_HAL_Is1msTickTimeout())
	{
		timerCnt++;
	}

	if(timerCnt >= 250u)
	{
		ToggleDebugIO();
                
		timerCnt = 0u;
	}

	if(TRUE == TIMER_HAL_Is100msTickTimeout())
	{
		WATCHDOG_HAL_Fed();
	}
	
}

void UDS_DoTxMsgCallback(void)
{
	if(NULL_PTR != g_TxMsgInfo.pfTxMsgCallback)
	{
		(g_TxMsgInfo.pfTxMsgCallback)();
		
		g_TxMsgInfo.pfTxMsgCallback = NULL_PTR;
	}
}


void UDS_RXMsgProcess(uint32 i_RxMsgId, uint32 i_RxMsgLen, uint8 *i_MsgBuf)
{
	uint8 index = 0u;
	uint8 msgLen = 0u;
	uint8 UDSserviceID = 0u;

	ASSERT(NULL_PTR == i_MsgBuf);

	if(0u == i_RxMsgLen)
	{
		return;
	}

#ifdef EN_CAN_TP
	if((RX_FUN_ID != i_RxMsgId) && (RX_PHY_ID != i_RxMsgId))
	{
		return;
	}

	g_RxMsgInfo.msgId = i_RxMsgId;
	g_RxMsgInfo.msgLen = i_RxMsgLen;
	for(index = 0u; index < g_RxMsgInfo.msgLen; index++)
	{
		g_RxMsgInfo.msgBuf[index] = i_MsgBuf[index];
	}

#elif (defined EN_LIN_TP)
	if((RX_FUN_ID != i_MsgBuf[0]) && (RX_PHY_ID != i_MsgBuf[0]) && RX_BOARD_ID != i_MsgBuf[0])
	{
		return;
	}

	g_RxMsgInfo.msgId = i_MsgBuf[0];
	g_RxMsgInfo.msgLen = i_RxMsgLen - 1;
	for(index = 0u; index < g_RxMsgInfo.msgLen; index++)
	{
		g_RxMsgInfo.msgBuf[index] = i_MsgBuf[index + 1];
	}
#else
#error "Please enable CAN/LIN TP"
#endif

	g_RxMsgInfo.pfTxMsgCallback = NULL_PTR;
	g_RxMsgInfo.isMsgValid = TRUE;
	UDSserviceID = g_RxMsgInfo.msgBuf[1u];

	switch(UDSserviceID)
	{
		case 0x10u:
			UDS_DiagnosticSession();

			break;

		case 0x28u:
			UDS_DisableTXAndRXNonDiagnosticMsg();

			break;

		case 0x85u:
			UDS_DisableRecordDTC();

			break;

		default:
#ifdef EN_CAN_TP
			g_TxMsgInfo.isMsgValid = TRUE;
			g_TxMsgInfo.msgLen = 8u;
			g_TxMsgInfo.msgId = TX_ID;
			g_TxMsgInfo.msgBuf[0u] = 0x03u;
			g_TxMsgInfo.msgBuf[1u] = 0x7Fu;
			g_TxMsgInfo.msgBuf[2u] = UDSserviceID;
			g_TxMsgInfo.msgBuf[3u] = 0x11u;
#elif defined EN_LIN_TP
			g_TxMsgInfo.msgId = 0x3Du;
			g_TxMsgInfo.msgBuf[0u] = TX_ID;
			g_TxMsgInfo.msgBuf[1u] = 0x02u;
			g_TxMsgInfo.msgBuf[2u] = 0x7Fu;
			g_TxMsgInfo.msgBuf[3u] = 0x11u;
#else
#error "Pls defined CAN/LIN TP!"
#endif			
			break;
	}

}

boolean UDS_GetTxMsgInfo(uint32 *o_pTxMsgId, uint32 *o_pTxMsgLen, uint8 *o_pTxMsgBuf)
{
    uint8 index = 0u;

	if((NULL_PTR == o_pTxMsgId) ||
	  (NULL_PTR == o_pTxMsgLen) ||
	  (NULL_PTR == o_pTxMsgBuf))
	{
		return FALSE;
	}

	if((FALSE == g_TxMsgInfo.isMsgValid) || (0u == g_TxMsgInfo.msgLen))
	{
		return FALSE;
	}

	*o_pTxMsgId = g_TxMsgInfo.msgId;
	*o_pTxMsgLen = g_TxMsgInfo.msgLen;
	for(index = 0u; index < g_TxMsgInfo.msgLen; index++)
	{
		o_pTxMsgBuf[index] = g_TxMsgInfo.msgBuf[index];
	}

	g_TxMsgInfo.isMsgValid = FALSE;
	g_TxMsgInfo.msgLen = 0u;
	g_TxMsgInfo.msgId = 0u;

	return TRUE;

}

boolean UDS_IsDataNeedTx(void)
{
	boolean ret = FALSE;

	if((TRUE == g_TxMsgInfo.isMsgValid) && (0u != g_TxMsgInfo.msgLen))
	{
		ret = TRUE;
	}

	return ret;
}

/*Do diagnostic session*/
static void UDS_DiagnosticSession(void)
{
	uint8 subService = 0u;
	uint8 txMsgBuf[8u];
	uint8_t txlen = 0;

	subService = g_RxMsgInfo.msgBuf[2];
	g_TxMsgInfo.msgLen = 8u;
	g_TxMsgInfo.pfTxMsgCallback = NULL_PTR;

	switch(subService)
	{		
		case 0x82u:
			g_TxMsgInfo.msgLen = 0u;
		case 0x02u:
			txlen = 3;
			txMsgBuf[0] = 0x7Fu;
			txMsgBuf[1] = 0x10;
			txMsgBuf[2] = 0x78;
			Boot_RequestEnterBootloader();
			g_TxMsgInfo.pfTxMsgCallback = &WATCHDOG_HAL_SystemRest;
			break;
		case 0x81u:
		case 0x83u:
			g_TxMsgInfo.msgLen = 0u;
		case 0x01u:
		case 0x03u:
			txlen = 2;
			txMsgBuf[0] = 0x50u;
			txMsgBuf[1] = subService;
			break;
		default :
			txlen = 3;
			txMsgBuf[0] = 0x7Fu;
			txMsgBuf[1] = 0x10u;
			txMsgBuf[2] = 0x12u;
			break;
	}

	g_TxMsgInfo.isMsgValid = TRUE;
#ifdef EN_CAN_TP
	g_TxMsgInfo.msgId = TX_ID;
	g_TxMsgInfo.msgBuf[0u] = txlen;
	g_TxMsgInfo.msgBuf[1u] = txMsgBuf[0];
	g_TxMsgInfo.msgBuf[2u] = txMsgBuf[1];
	g_TxMsgInfo.msgBuf[3u] = txMsgBuf[2];
#elif defined EN_LIN_TP
	g_TxMsgInfo.msgId = 0x3Du;
	g_TxMsgInfo.msgBuf[0u] = TX_ID;
	g_TxMsgInfo.msgBuf[1u] = txlen;
	g_TxMsgInfo.msgBuf[2u] = txMsgBuf[0];
	g_TxMsgInfo.msgBuf[3u] = txMsgBuf[1];
	g_TxMsgInfo.msgBuf[4u] = txMsgBuf[2];
#else
#error "Pls defined CAN/LIN TP!"
#endif
}

/*Do disable TX and RX non diagnostic message*/
static void UDS_DisableTXAndRXNonDiagnosticMsg(void)
{
	uint8 subService = 0u;
	uint8 txMsgBuf[8u];
	uint8_t txlen = 0;

	subService = g_RxMsgInfo.msgBuf[2];
	g_TxMsgInfo.msgLen = 8u;
	g_TxMsgInfo.pfTxMsgCallback = NULL_PTR;

	switch(subService)
	{
		case 0x80u:
		case 0x83u:
			g_TxMsgInfo.msgLen = 0u;
		case 0x00u:
		case 0x03u:
			txlen = 2;
		    txMsgBuf[0] = 0x68u;
			txMsgBuf[1] = subService;
			break;

		default :
			txlen = 3;
			txMsgBuf[0] = 0x7Fu;
			txMsgBuf[1] = subService;
			txMsgBuf[2] = 0x11u;
			break;
	}

	g_TxMsgInfo.isMsgValid = TRUE;


#ifdef EN_CAN_TP
	g_TxMsgInfo.msgId = TX_ID;
	g_TxMsgInfo.msgBuf[0u] = txlen;
	g_TxMsgInfo.msgBuf[1u] = txMsgBuf[0];
	g_TxMsgInfo.msgBuf[2u] = txMsgBuf[1];
	g_TxMsgInfo.msgBuf[3u] = txMsgBuf[2];
#elif defined EN_LIN_TP
	g_TxMsgInfo.msgId = 0x3Du;
	g_TxMsgInfo.msgBuf[0u] = TX_ID;
	g_TxMsgInfo.msgBuf[1u] = 0x02;
	g_TxMsgInfo.msgBuf[2u] = txMsgBuf[0];
	g_TxMsgInfo.msgBuf[3u] = txMsgBuf[1];
#else
#error "Pls defined CAN/LIN TP!"
#endif
}

/*Do disable record DTC*/
static void UDS_DisableRecordDTC(void)
{
	uint8 subService = 0u;
	uint8 txMsgBuf[8u];
	uint8_t txlen = 0;

	subService = g_RxMsgInfo.msgBuf[2];
	g_TxMsgInfo.msgLen = 8u;
	g_TxMsgInfo.pfTxMsgCallback = NULL_PTR;

	switch(subService)
	{
		case 0x81u:
		case 0x82u:
			g_TxMsgInfo.msgLen = 0u;	
		case 0x01u:
		case 0x02u:
			txlen = 2;
		    txMsgBuf[0] = 0x85u + 0x40u;
			txMsgBuf[1] = subService;
			break;
		default :
			txlen = 3;
			txMsgBuf[0] = 0x7Fu;
			txMsgBuf[1] = subService;
			txMsgBuf[2] = 0x11u;
			break;
	}

	g_TxMsgInfo.isMsgValid = TRUE;


#ifdef EN_CAN_TP
	g_TxMsgInfo.msgId = TX_ID;
	g_TxMsgInfo.msgBuf[0u] = txlen;
	g_TxMsgInfo.msgBuf[1u] = txMsgBuf[0];
	g_TxMsgInfo.msgBuf[2u] = txMsgBuf[1];
	g_TxMsgInfo.msgBuf[3u] = txMsgBuf[2];
#elif defined EN_LIN_TP
	g_TxMsgInfo.msgId = 0x3Du;
	g_TxMsgInfo.msgBuf[0u] = TX_ID;
	g_TxMsgInfo.msgBuf[1u] = 0x02;
	g_TxMsgInfo.msgBuf[2u] = txMsgBuf[0];
	g_TxMsgInfo.msgBuf[3u] = txMsgBuf[1];
#else
#error "Pls defined CAN/LIN TP!"
#endif
}

boolean UDS_TxMsgToHost(void)
{
	g_TxMsgInfo.msgLen = 8u;
	g_TxMsgInfo.pfTxMsgCallback = NULL_PTR;
	g_TxMsgInfo.isMsgValid = TRUE;
#ifdef EN_CAN_TP
	g_TxMsgInfo.msgId = TX_ID;
	g_TxMsgInfo.msgBuf[0u] = 0x02;
	g_TxMsgInfo.msgBuf[1u] = 0x51u;
	g_TxMsgInfo.msgBuf[2u] = 0x01u;
#elif defined EN_LIN_TP
	g_TxMsgInfo.msgId = 0x3Du;
	g_TxMsgInfo.msgBuf[0u] = TX_ID;
	g_TxMsgInfo.msgBuf[1u] = 0x02;
	g_TxMsgInfo.msgBuf[2u] = 0x51u;
	g_TxMsgInfo.msgBuf[3u] = 0x01u;
#else
#error "Pls defined CAN/LIN TP!"
#endif

	return TRUE;
}
